package servlet;

import bean.CAF;
import bean.Page;
import dao.CAFDao;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import util.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 资讯反馈（前台）对应的servlrt
 *
 * @author dsf
 * @date|time 2017/9/11|10:44
 * @update:
 */
@WebServlet(name = "CAF", urlPatterns = {"/caf"})
public class CAFServlet extends HttpServlet {

    /**
     * 添加咨询反馈
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String serverCheckcode = req.getSession().getAttribute("code").toString().substring(4, 8);
        System.out.println("doPost();" + serverCheckcode + "end");
        //存储用户输入的表单项
        CAF cafPara = new CAF();
        //id自增，参数置为null
        cafPara.setCafId(null);
        //把不需要从用户提交表单获取数据的参数项设置好
        SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
        cafPara.setCafPostDate(df.format(new Date()));
        cafPara.setCafReplyDate(null);
        cafPara.setCafSolvedStatus("0");
        cafPara.setCafReply(null);
        String userName = "";
        //得到上传文件的保存目录，将上传的文件存放于WEB-INF目录下，不允许外界直接访问，保证上传文件的安全
        String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
        //上传时生成的临时文件保存目录
        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
        File tmpFile = new File(tempPath);
        if (!tmpFile.exists()) {
            //创建临时目录
            tmpFile.mkdir();
        }
        try {
            //1、创建一个DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置工厂的缓冲区的大小，当上传的文件大小超过缓冲区的大小时，就会生成一个临时文件存放到指定的临时目录当中。
            factory.setSizeThreshold(1024 * 100);//设置缓冲区的大小为100KB，如果不指定，那么缓冲区的大小默认是10KB
            //设置上传时生成的临时文件的保存目录
            factory.setRepository(tmpFile);
            //2、创建一个文件上传解析器
            ServletFileUpload upload = new ServletFileUpload(factory);
            //解决上传文件名的中文乱码
            upload.setHeaderEncoding("UTF-8");
            //3、判断提交上来的数据是否是上传表单的数据
            if (!ServletFileUpload.isMultipartContent(req)) {
                //按照传统方式获取数据
            }
            //设置上传单个文件的大小的最大值，目前是设置为5MB
            upload.setFileSizeMax(1024 * 1024 * 5);
            //TODO 暂时只支持上传单个附件？
            //设置上传文件总量的最大值，最大值=同时上传的多个文件的大小的最大值的和，目前设置为5MB
            upload.setSizeMax(1024 * 1024 * 5);
            //4、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
            List<FileItem> list = upload.parseRequest(req);

            //把获取到的表单项加入参数
            cafPara.setCafTitle(list.get(0).getString("UTF-8"));
            cafPara.setDepId("1");
            cafPara.setCafType(list.get(2).getString("UTF-8"));
            cafPara.setCafPublic(list.get(3).getString("UTF-8"));
            userName = list.get(4).getString("UTF-8");
            cafPara.setName(userName);
            cafPara.setPhone(list.get(5).getString("UTF-8"));
            cafPara.setAddress(list.get(6).getString("UTF-8"));
            cafPara.setEmail(list.get(7).getString("UTF-8"));
            cafPara.setCafContent(list.get(8).getString("UTF-8"));
            String filename = list.get(9).getName();
            String userCheckCode = list.get(10).getString("UTF-8");
            if (userCheckCode.equals(serverCheckcode)) {//将客户端验证码和服务器端验证比较，如果相等，则表示验证通过
                System.out.println("验证码验证通过！");
            } else {
                System.out.println("验证码验证失败！");
                resp.setContentType("text/html;charset=utf-8");
                PrintWriter out = resp.getWriter();
                out.write("<script language='javascript'>alert('失败:验证码输入错误！');</script>");

                //验证码验证失败，把用户提交上来的表单数据放回去
                req.setAttribute("title", list.get(0).getString("UTF-8"));
                req.setAttribute("name", userName);
                req.setAttribute("phone", list.get(5).getString("UTF-8"));
                req.setAttribute("address", list.get(6).getString("UTF-8"));
                req.setAttribute("email", list.get(7).getString("UTF-8"));
                req.setAttribute("content", list.get(8).getString("UTF-8"));
                req.setAttribute("imgcode", list.get(10).getString("UTF-8"));
                //在页面输出错误提示
                req.setAttribute("error_imgcode", "验证码输入错误！");
                req.getRequestDispatcher("/caf/caf.jsp").forward(req, resp);
                return;
            }
            System.out.println(filename);
            if (filename == null || filename.trim().equals("")) {
                cafPara.setCafFile(filename);
            } else {
                //注意：不同的浏览器提交的文件名是不一样的，有些浏览器提交上来的文件名是带有路径的，如：  c:\a\b\1.txt，而有些只是单纯的文件名，如：1.txt
                //处理获取到的上传文件的文件名的路径部分，只保留文件名部分
                filename = filename.substring(filename.lastIndexOf("\\") + 1);
                //得到上传文件的扩展名
                String fileExtName = filename.substring(filename.lastIndexOf(".") + 1);
                //如果需要限制上传的文件类型，那么可以通过文件的扩展名来判断上传的文件类型是否合法
                System.out.println("上传的文件的扩展名是：" + fileExtName);
                if (Db2PageUtil.cafFile(fileExtName) != "OK") {
                    System.out.println("文件类型不合法！");
                    req.getRequestDispatcher("/caf/caf.jsp").forward(req, resp);
                    return;
                } else {
                    //获取item中的上传文件的输入流
                    InputStream in = list.get(9).getInputStream();
                    //得到文件保存的名称
                    String saveFilename = UploadSaveUtil.makeFileName(filename);
                    System.out.println(saveFilename);
                    //得到文件的保存目录
                    String realSavePath = UploadSaveUtil.makePath(saveFilename, savePath);
                    System.out.println(realSavePath + "\\" + saveFilename);

                    //把文件名加入参数项
                    cafPara.setCafFile(saveFilename);
                    //创建一个文件输出流
                    FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
                    //创建一个缓冲区
                    byte buffer[] = new byte[1024];
                    //判断输入流中的数据是否已经读完的标识
                    int len = 0;
                    //循环将输入流读入到缓冲区当中，(len=in.read(buffer))>0就表示in里面还有数据
                    while ((len = in.read(buffer)) > 0) {
                        //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                        out.write(buffer, 0, len);
                    }
                    //关闭输入输出流
                    in.close();
                    out.close();
                    System.out.println("文件上传成功！");
                }
            }

            //获取一个UUID作为查询码先插入数据库中
            String skTemp = UUIDUtil.getUUID();
            cafPara.setCafSearchKey(skTemp);

            Connect con = Connect.getInstance();

            System.out.println(cafPara.getCafTitle());
            try {
                int cafRes = CAFDao.cafAdd(cafPara, con);
                if (cafRes != 0) System.out.println("保存表单项成功！");
                else System.out.println("保存表单项失败！");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("保存表单项失败！");
            }
            List<CAF> cafRes;
            CAF getIdBySK = new CAF();
            getIdBySK.setCafSearchKey(skTemp);
            try {
                //从数据库获取刚刚插入时生成的id
                cafRes = CAFDao.search(getIdBySK, null, con);
                if (cafRes.size() != 0) {
                    CAF caf1 = cafRes.get(0);
                    String id = caf1.getCafId();
                    //根据id和类型标识生成查询码
                    String SK = SearchKeyUtil.getSearchKey(id, 'C');
                    resp.setContentType("text/html;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write(SK + "<script language='javascript'>alert('您的留言我们已经接收到！');</script>");
                    System.out.println(SK);
                    CAF saveSKRoDB = new CAF();
                    saveSKRoDB.setCafId(id);
                    saveSKRoDB.setCafSearchKey(SK);
                    int saveSkRes = CAFDao.cafModify(saveSKRoDB, con);
                    if (saveSkRes != 0) {
                        req.setAttribute("SK", SK);
                        req.setAttribute("userName", userName);
                        resp.sendRedirect("/caf?t=s&sk=" + SK);
                        System.out.println("保存查询码成功！");
                    } else System.out.println("保存查询码失败！");
                } else {
                    System.out.println("保存查询码失败。");
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("依据SKtemp从数据库获取id失败。");
            }
        } catch (FileUploadBase.FileSizeLimitExceededException e) {
            e.printStackTrace();
            System.out.println("单个文件超出最大值。");
        } catch (FileUploadBase.SizeLimitExceededException e) {
            e.printStackTrace();
            System.out.println("上传文件的总的大小超出限制的最大值。");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("文件上传失败！");
        }
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String t = req.getParameter("t");
        if (t.equals("public")) {
            doPublic(req, resp);
        }
        if (t.equals("detail")) {
            doDeatil(req, resp);
        }
        if (t.equals("search")) {
            doSearch(req, resp);
        }
        if (t.equals("s")) {
            doSuccess(req, resp);
        }
    }

    /**
     * 查看公开的留言一览界面
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    private void doPublic(HttpServletRequest req,
                          HttpServletResponse resp) throws ServletException, IOException {
        String page = "1";
        if (StringUtil.isNotEmpty(req.getParameter("page")))
            page = req.getParameter("page");
        int pageInt = Integer.parseInt(page);
        Connect con = Connect.getInstance();
        CAF cafPublicPara = new CAF();
        Page cafPagePara = new Page();
        cafPagePara.setSize(10);
        int pageSize = cafPagePara.getSize();
        //查找所有可以公开的条目
        cafPublicPara.setCafPublic("1");
        List<CAF> cafRes;
        //TODO caf前台分页
        //从数据库获取刚刚插入时生成的id
        try {
            //数据条数
            int cafResCount = CAFDao.cafCount(cafPublicPara, con);
            // 总分页数
            int pageNum = cafResCount % pageSize == 0 ? cafResCount / pageSize : cafResCount / pageSize + 1;
            if (pageInt > pageNum)// 最后一页数据被删除完后跳到第一页
                pageInt = 1;
            cafPagePara.setStart((pageInt - 1) * cafPagePara.getSize());
            System.out.println(cafPagePara.getSize() + "页数" + pageNum);
            cafRes = CAFDao.search(cafPublicPara, cafPagePara, con);

            req.setAttribute("cafRes", cafRes);
            req.setAttribute("pagenum", pageNum);// 总页数
            req.setAttribute("page", page);// 当前页
            System.out.println(page);
            req.setAttribute("count", cafResCount);
            req.getRequestDispatcher("/caf/search.jsp").forward(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 查看公开留言的详细信息（不包含留言人的个人隐私信息）
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    private void doDeatil(HttpServletRequest req,
                          HttpServletResponse resp) throws ServletException, IOException {
        String cafId = req.getParameter("id");

        Connect con = Connect.getInstance();
        CAF cafDetailPara = new CAF();
        cafDetailPara.setCafId(cafId);
        List<CAF> cafRes;
        try {
            cafRes = CAFDao.search(cafDetailPara, null, con);
            req.setAttribute("cafRes", cafRes);
            req.getRequestDispatcher("/caf/cafinfo.jsp").forward(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据查询码查询留言的详细信息（包含个人隐私信息）
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    private void doDeatilBySK(HttpServletRequest req,
                              HttpServletResponse resp) throws ServletException, IOException {
        String SK = req.getParameter("sk");
        System.out.println("查询码以键入" + SK);
        Connect con = Connect.getInstance();
        CAF cafSearchBySKPara = new CAF();
        cafSearchBySKPara.setCafSearchKey(SK);
        List<CAF> cafRes;
        try {
            cafRes = CAFDao.search(cafSearchBySKPara, null, con);
            //TODO 把取得的depId转换为depName，在展示给用户
            if (cafRes.size() == 0) {
                System.out.println("查询码不存在！");
                req.setAttribute("error_sk", "查询码不存在！");
                req.getRequestDispatcher("/caf?t=public").forward(req, resp);
            } else {
                req.setAttribute("cafRes", cafRes);
                req.getRequestDispatcher("/caf/cafinfosk.jsp").forward(req, resp);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("依据查询码获取id失败");
            //  doPublic(req, resp);
        }
    }

    /**
     * 按条件查询（标题和留言类型，潜在条件cafPublic=1）
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    private void doSearch(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String cafTitle = req.getParameter("title");
        String cafType = req.getParameter("type");
        String SK = req.getParameter("sk");
        String page = "1";
        if (StringUtil.isNotEmpty(req.getParameter("page")))
            page = req.getParameter("page");
        Page cafPagePara = new Page();
        cafPagePara.setSize(10);
        int pageSize = cafPagePara.getSize();

        if (StringUtil.isNotEmpty(req.getParameter("page"))) {
            page = req.getParameter("page");
        }
        int pageInt = Integer.parseInt(page);
        if (StringUtil.isEmpty(cafTitle) && StringUtil.isEmpty(cafType) && StringUtil.isEmpty(SK)) {
            req.setAttribute("page", "1");// 当前页置为1
            doPublic(req, resp);
        } else {
            if (StringUtil.isNotEmpty(SK)) {
                doDeatilBySK(req, resp);
            } else {
                Connect con = Connect.getInstance();
                CAF cafSearchPara = new CAF();

                cafSearchPara.setCafTitle(cafTitle);
                cafSearchPara.setCafType(cafType);
                cafSearchPara.setCafPublic("1");
                List<CAF> cafRes;
                try {
                    //数据条数
                    int cafResCount = CAFDao.cafCount(cafSearchPara, con);
                    // 总分页数
                    int pageNum = cafResCount % pageSize == 0 ? cafResCount / pageSize : cafResCount / pageSize + 1;
                    if (pageInt > pageNum)// 最后一页数据被删除完后跳到第一页
                        pageInt = 1;
                    cafPagePara.setStart((pageInt - 1) * cafPagePara.getSize());
                    System.out.println(cafPagePara.getSize());

                    cafRes = CAFDao.search(cafSearchPara, cafPagePara, con);
                    req.setAttribute("pagenum", pageNum);// 总页数
                    req.setAttribute("page", page);// 当前页
                    System.out.println(page);
                    req.setAttribute("count", cafResCount);
                    req.setAttribute("cafRes", cafRes);
                    req.setAttribute("title", cafTitle);
                    req.setAttribute("type", cafType);
                    req.getRequestDispatcher("/caf/search.jsp").forward(req, resp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 添加留言成功，向用户展示 唯一查询码和查询码对应的二维码
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    private void doSuccess(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String SK = req.getParameter("sk");
        System.out.println(SK);
        if (SearchKeyUtil.isSearchKey(SK)) {
            req.setAttribute("SK", SK);
            req.getRequestDispatcher("/caf/success.jsp").forward(req, resp);
        } else {
            System.out.println("查询码格式错误！");
        }
    }
}